package com.ruoyi.framework.config.mybatisplus.handler;

import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.Parenthesis;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Slf4j
public class MyDataPermissionHandler implements DataPermissionHandler {

    /**
     * 全部数据权限
     */
    public static final String DATA_SCOPE_ALL = "1";

    /**
     * 自定数据权限
     */
    public static final String DATA_SCOPE_CUSTOM = "2";

    /**
     * 部门数据权限
     */
    public static final String DATA_SCOPE_DEPT = "3";

    /**
     * 部门及以下数据权限
     */
    public static final String DATA_SCOPE_DEPT_AND_CHILD = "4";

    /**
     * 仅本人数据权限
     */
    public static final String DATA_SCOPE_SELF = "5";

    @Override
    public Expression getSqlSegment(Expression where, String mappedStatementId) {

        /**
         * 以下模块不进行数据权限控制
         */
        List<String> ignoreMapper = Arrays.asList(new String[]{
                "com.ruoyi.system.mapper", //系统模块
                "com.ruoyi.quartz.mapper",  //定时任务
                "com.ruoyi.generator.mapper" //代码生成
        });
        for (String ignore : ignoreMapper) {
            if (mappedStatementId.startsWith(ignore)) {
                return where;
            }
        }

        /**
         * 当前用户
         */
        SysUser user = SecurityUtils.getLoginUser().getUser();

        /**
         * 管理员获取全部数据
         */
        if (user.isAdmin()) {
            return where;
        }

        /**
         * 获取数据过滤SQL
         */
        String dataFilterSql = buildDataFilter(user);

        if (StringUtils.isBlank(dataFilterSql)) {
            return where;
        }
        try {
            Expression expression = CCJSqlParserUtil.parseExpression(dataFilterSql);
            // 数据权限使用单独的括号 防止与其他条件冲突
            Parenthesis parenthesis = new Parenthesis(expression);
            if (StringUtils.isNotNull(where)) {
                return new AndExpression(where, parenthesis);
            } else {
                return parenthesis;
            }
        } catch (JSQLParserException e) {
            throw new ServiceException("数据权限解析异常 => " + e.getMessage());
        }

    }

    /**
     * 组装SQL条件字符
     *
     * @param user
     * @return
     */
    private String buildDataFilter(SysUser user) {

        StringBuilder sqlString = new StringBuilder();

        Set<String> dis = new HashSet<>();

        /**
         * 获取当前用户角色
         */
        for (SysRole role : user.getRoles()) {
            String dataScope = role.getDataScope();
            int size = dis.size();
            dis.add(dataScope);
            if (DATA_SCOPE_ALL.equals(dataScope) && size != dis.size()) {
                //全部
                sqlString = new StringBuilder();
                break;
            } else if (DATA_SCOPE_CUSTOM.equals(dataScope) && size != dis.size()) {
                //自定数据权限
                sqlString.append(
                        StringUtils.format(
                                "add_user IN ( select user_name from sys_user stu,sys_role_dept srd where stu.dept_id=srd.dept_id and role_id= '{}' ) ",
                                role.getRoleId()));
            } else if (DATA_SCOPE_DEPT.equals(dataScope) && size != dis.size()) {
                //当前部门数据权限
                sqlString.append(
                        StringUtils.format(
                                "add_user IN (select user_name from sys_user where dept_id= '{}' ) ",
                                user.getDeptId()));
            } else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope) && size != dis.size()) {
                //部门及以下数据权限
                sqlString.append(
                        StringUtils.format(
                                "add_user IN ( select user_name FROM sys_user stu,sys_dept sd WHERE stu.dept_id=sd.dept_id and (sd.dept_id = '{}' or find_in_set( '{}' , sd.ancestors )) )",
                                user.getDeptId(), user.getDeptId()));
            } else if (DATA_SCOPE_SELF.equals(dataScope) && size != dis.size()) {
                //仅本人数据权限
                sqlString.append(StringUtils.format("add_user = '{}' ", user.getUserName()));
            }
        }
        return sqlString.toString();
    }
}
